package cn.backpackerxl.easyJDBC.main;

import cn.backpackerxl.easyJDBC.mrss.EasyJDBCModify;
import cn.backpackerxl.easyJDBC.mrss.EasyJDBCRemove;
import cn.backpackerxl.easyJDBC.mrss.EasyJDBCSave;
import cn.backpackerxl.easyJDBC.mrss.EasyJDBCSelect;
import cn.backpackerxl.easyJDBC.util.*;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

import static cn.backpackerxl.easyJDBC.util.BeanUtil.*;
import static cn.backpackerxl.easyJDBC.util.SqlFactory.getSQLByStackTraceElement;


/**
 * EasyJDBC增删改入口类
 * <p>
 * author: backpackerxl
 * create: 2021/12/23
 * filename: EasyJDBCExecutor
 **/
public class EasyJDBCExecutor<E, T> implements EasyJDBCRef<E>, EasyJDBCRefPlus<E, T> {
    private final EasyJDBCSave easyJDBCSave = new EasyJDBCSave();
    private final EasyJDBCSelect<E> easyJDBCSelect = new EasyJDBCSelect<>();
    private final EasyJDBCModify easyJDBCModify = new EasyJDBCModify();
    private final EasyJDBCRemove<E> easyJDBCRemove = new EasyJDBCRemove<>();

    private String packName;
    private String target;

    private Method[] methods;

    static {
        CreateTable.run();
    }

    /**
     * 设置主要查询对象
     *
     * @param packName 主要查询对象
     */
    private void setClazz(String packName) {
        this.packName = packName;
    }

    /**
     * 设置次要查询对象及主要
     *
     * @param packName 主要查询对象
     * @param target   次要查询对象
     */
    private void setClazz(String packName, String target) {
        this.packName = packName;
        this.target = target;
    }

    /**
     * 设置调用者的所有方法
     *
     * @param mds 所有方法
     */
    private void setMethods(Method[] mds) {
        this.methods = mds;
    }

    /**
     * 增加
     *
     * @param e 增加对象
     * @return 0 -> 代表处理失败 1 -> 代表处理成功
     */
    public int save(E e) {
        return easyJDBCSave.saveToTable(BeanUtil.getBean(e).getTableName(), e.getClass().getDeclaredFields(), e);
    }

    /**
     * 批量插入
     *
     * @param data 大量数据
     */
    public void saveBatch(List<E> data) {
        for (E datum : data) {
            save(datum);
        }
    }

    /**
     * 修改
     *
     * @param e 修改对象
     * @return 0 -> 代表处理失败 1 -> 代表处理成功
     */
    public int update(E e) {
        return easyJDBCModify.update(BeanUtil.getBean(e).getTableName(), e.getClass().getDeclaredFields(), e);
    }

    /**
     * 删除
     *
     * @param id -> 删除Id
     * @return 0 -> 代表处理失败 1 -> 代表处理成功
     */
    public int remove(Long id) {
        return easyJDBCRemove.remove(id, createBeanFactory(this.packName));
    }

    /**
     * 查询
     *
     * @param id -> 查询id
     * @return 查询结果
     */
    public E findById(Long id) {
        return easyJDBCSelect.findById(id, createBeanFactory(this.packName));
    }

    /**
     * 查询表中所有数据
     *
     * @return 数据列表
     */
    public List<E> findAll() {
        return easyJDBCSelect.findAll(createBeanFactory(this.packName));
    }

    /**
     * 用于登录判断
     *
     * @param one   其中一个字段
     * @param other 另一个字段
     * @return 查询结果
     */
    public E findByOneAndOther(String one, String other) {
        return easyJDBCSelect.findByOneAndOther(one, other, createBeanFactory(this.packName), SqlFactory.getFields(Thread.currentThread(), this.methods, MySQL.AND));
    }

    /**
     * 用于校验注册
     *
     * @param one   其中一个字段
     * @param other 另一个字段
     * @return 查询结果列表
     */
    public List<E> findByOneOrOther(String one, String other) {
        return easyJDBCSelect.findByOneOrOther(one, other, createBeanFactory(this.packName), SqlFactory.getFields(Thread.currentThread(), this.methods, MySQL.OR));
    }

    /**
     * 用于通过单个字段进行查询
     *
     * @param one 查询参数
     * @return 满足条件的结果集
     */
    public List<E> findByOne(String one) {
        return easyJDBCSelect.findByOne(one, SqlFactory.getField(Thread.currentThread(), this.methods), createBeanFactory(this.packName));
    }

    /**
     * 将数据进行分页展示
     *
     * @param pageSize    每一页的数据量
     * @param currentPage 当前页数
     * @return 分页对象
     */
    public PageBean<E> pageEntityAll(int pageSize, int currentPage) {
        return easyJDBCSelect.pageEntityAll(pageSize, currentPage, createBeanFactory(this.packName));
    }

    /**
     * 普通搜索
     *
     * @param key 搜索关键词
     * @return 搜索结果列表
     */
    public List<E> search(String key) {
        return easyJDBCSelect.search(key, SqlFactory.getField(Thread.currentThread(), this.methods), createBeanFactory(this.packName));
    }

    /**
     * 将查询结果按分页形式进行展示
     *
     * @param key 关键字
     * @return 分页对象
     */
    public PageBean<E> search(String key, int pageSize, int currentPage) {
        return easyJDBCSelect.search(key, SqlFactory.getField(Thread.currentThread(), this.methods), pageSize, currentPage, createBeanFactory(this.packName));
    }

    /**
     * 多表连接查询
     *
     * @return 复杂类型数据
     */
    public List<T> findByJoin() {
        return easyJDBCSelect.findByJoin(getSQLByStackTraceElement(Thread.currentThread(), this.methods), createTarget(this.target));
    }

    /**
     * 按参数多表连接查询
     *
     * @param args 参数数组
     * @return 复杂类型数据
     */
    public List<T> findByJoin(Object... args) {
        return easyJDBCSelect.findByJoin(getSQLByStackTraceElement(Thread.currentThread(), this.methods), createTarget(this.target), args);
    }

    /**
     * 自定义查询
     *
     * @param args 参数数组
     * @return 对应实体列表的数据结构
     */
    public List<E> findByQuery(Object... args) {
        return easyJDBCSelect.findByQuery(getSQLByStackTraceElement(Thread.currentThread(), this.methods), createBeanFactory(this.packName), args);
    }

    /**
     * 根据SQL碎片进行连接查询
     *
     * @param clazz       第二张实体表
     * @param sqlFragment SQL碎片
     * @return 查询结果
     */
    @Override
    public List<T> findByJoin(Class<?> clazz, SQLFragments sqlFragment) {
        E beanFactory = createBeanFactory(this.packName);
        T t = createTarget(this.target);
        Objects.requireNonNull(beanFactory);
        Objects.requireNonNull(t);
        return easyJDBCSelect.findByJoin(sqlFragment.compile(BeanUtil.getBean(beanFactory), BeanUtil.getBean(createObj(clazz))), t);
    }

    /**
     * 根据SQL碎片进行连接查询
     *
     * @param clazz       第二张实体表
     * @param sqlFragment SQL碎片
     * @param args        条件参数
     * @return 查询结果
     */
    @Override
    public List<T> findByJoin(Class<?> clazz, SQLFragments sqlFragment, Object... args) {
        E beanFactory = createBeanFactory(this.packName);
        T t = createTarget(this.target);
        Objects.requireNonNull(beanFactory);
        Objects.requireNonNull(t);
        return easyJDBCSelect.findByJoin(sqlFragment.compile(BeanUtil.getBean(beanFactory), BeanUtil.getBean(createObj(clazz))), t, args);
    }

    /**
     * 根据SQL碎片进行自定义查询
     *
     * @param sqlFragment SQL碎片
     * @param args        条件参数
     * @return 查询结果
     */
    @Override
    public List<E> findByQuery(SQLFragment sqlFragment, Object... args) {
        E beanFactory = createBeanFactory(this.packName);
        Objects.requireNonNull(beanFactory);
        return easyJDBCSelect.findByQuery(sqlFragment.compile(BeanUtil.getBean(beanFactory)), beanFactory, args);
    }
}
